//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package main

import (
	"context"
	"errors"
	"fmt"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"

	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_appstore_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_auth_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_auth_user_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_client_cfg_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_events_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_feedback_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_idea_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_keyword_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_org_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_org_member_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_project_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_project_member_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_roadmap_api_serv"
	admin_sw_strore_api_serv "atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_sw_store_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_user_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_user_resume_api_serv"
	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_widget_store_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/api_collection_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/appstore_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/client_cfg_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/dataview_chat_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/events_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/feedback_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/fs_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/http_custom_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/idea_store_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/org_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/org_evaluate_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/org_forum_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/org_member_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/org_okr_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/org_report_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_alarm_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_bulletin_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_code_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_comment_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_dataview_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_doc_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_draw_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_entry_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_git_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_idea_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_issue_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_member_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_recycle_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_requirement_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_review_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_server_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_sprit_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_testcase_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/project_triger_api_serv"
	project_watch_api_serv "atomgit.com/openlinksaas-org/api-server/api_serv/project_watch_api_srev"
	"atomgit.com/openlinksaas-org/api-server/api_serv/roadmap_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/roadmap_content_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/roadmap_state_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/roadmap_user_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/short_note_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/sw_store_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/user_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/user_app_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/user_mail_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/user_memo_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/user_resume_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/user_todo_api_serv"
	"atomgit.com/openlinksaas-org/api-server/api_serv/widget_store_api_serv"
	"atomgit.com/openlinksaas-org/api-server/bg_runner"
	"atomgit.com/openlinksaas-org/api-server/config"
	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/mail_serv"
	"atomgit.com/openlinksaas-org/api-server/metric_serv"
	"atomgit.com/openlinksaas-org/api-server/notice_serv"
	"atomgit.com/openlinksaas-org/api-server/upgrade"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/admin_auth_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/api_collection_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/appstore_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/client_cfg_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/dataview_chat_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/events_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/feedback_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/fs_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/http_custom_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/idea_store_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/keyword_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/org_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/org_evaluate_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/org_forum_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/org_member_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/org_okr_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/org_report_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_alarm_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_bulletin_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_code_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_comment_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_dataview_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_doc_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_draw_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_entry_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_git_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_idea_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_issue_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_member_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_recycle_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_requirement_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_review_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_server_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_sprit_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_testcase_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_triger_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_watch_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/roadmap_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/roadmap_content_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/roadmap_state_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/roadmap_user_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/short_note_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/sw_store_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/user_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/user_app_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/user_mail_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/user_memo_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/user_resume_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/user_todo_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/widget_store_api"
	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
	grpc_zap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap"
	grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
	"github.com/redis/go-redis/v9"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo"
	"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"google.golang.org/grpc"
	"gopkg.in/natefinch/lumberjack.v2"
)

const (
	VERSION = "0.3.45"
)

var grpcServer *grpc.Server

func connMongoDb(dbUrl, dbName string) (*mongo.Database, error) {
	clientOpts := options.Client().ApplyURI(dbUrl).SetConnectTimeout(10 * time.Second)
	clientOpts.Monitor = otelmongo.NewMonitor()
	client, err := mongo.Connect(context.Background(), clientOpts)
	if err != nil {
		return nil, err
	}
	return client.Database(dbName), nil
}

func runGrpcServer(servCfg *config.ServerConfig, grpcLogger, errLogger *zap.Logger, exitChan chan error) {
	optionList := []grpc.ServerOption{
		grpc.StreamInterceptor(
			grpc_middleware.ChainStreamServer(
				grpc_zap.StreamServerInterceptor(grpcLogger),
				grpc_recovery.StreamServerInterceptor(),
				metric_serv.StreamServerInterceptor(),
			)),
		grpc.UnaryInterceptor(
			grpc_middleware.ChainUnaryServer(
				grpc_zap.UnaryServerInterceptor(grpcLogger),
				grpc_recovery.UnaryServerInterceptor(),
				metric_serv.UnaryServerInterceptor(),
			)),
	}
	if servCfg.Trace.Addr != "" {
		optionList = append(optionList, grpc.StatsHandler(otelgrpc.NewServerHandler()))
	}
	grpcServer = grpc.NewServer(optionList...)

	client_cfg_api.RegisterClientCfgApiServer(grpcServer, client_cfg_api_serv.NewClientCfgApiImpl(servCfg, errLogger))
	user_api.RegisterUserApiServer(grpcServer, user_api_serv.NewUserApiImpl(servCfg))
	user_resume_api.RegisterUserResumeApiServer(grpcServer, &user_resume_api_serv.UserResumeApiImpl{})
	user_memo_api.RegisterUserMemoApiServer(grpcServer, &user_memo_api_serv.UserMemoApiImpl{})
	user_todo_api.RegisterUserTodoApiServer(grpcServer, &user_todo_api_serv.UserTodoApiImpl{})
	user_app_api.RegisterUserAppApiServer(grpcServer, &user_app_api_serv.UserAppApi{})
	user_mail_api.RegisterUserMailApiServer(grpcServer, user_mail_api_serv.NewUserMailApiImpl(&servCfg.ClientCfg))
	project_api.RegisterProjectApiServer(grpcServer, &project_api_serv.ProjectApiImpl{})
	project_member_api.RegisterProjectMemberApiServer(grpcServer, &project_member_api_serv.ProjectMemberApiImpl{})
	fs_api.RegisterFsApiServer(grpcServer, fs_api_serv.NewProjectFsApiImpl(servCfg.DataBase.FileStore.RemoteAddr))
	events_api.RegisterEventsApiServer(grpcServer, &events_api_serv.EventsApiImpl{})
	project_issue_api.RegisterProjectIssueApiServer(grpcServer, &project_issue_api_serv.ProjectIssueApiImpl{})
	project_sprit_api.RegisterProjectSpritApiServer(grpcServer, &project_sprit_api_serv.ProjectSpritApiImpl{})
	project_doc_api.RegisterProjectDocApiServer(grpcServer, &project_doc_api_serv.ProjectDocApiImpl{})
	project_draw_api.RegisterProjectDrawApiServer(grpcServer, &project_draw_api_serv.ProjectDrawApiImpl{})
	project_entry_api.RegisterProjectEntryApiServer(grpcServer, &project_entry_api_serv.ProjectEntryApiImpl{})
	short_note_api.RegisterShortNoteApiServer(grpcServer, &short_note_api_serv.ShortNoteApiImpl{})
	project_requirement_api.RegisterProjectRequirementApiServer(grpcServer, &project_requirement_api_serv.ProjectRequirementApiImpl{})
	appstore_api.RegisterAppstoreApiServer(grpcServer, &appstore_api_serv.AppstoreApiImpl{})
	project_code_api.RegisterProjectCodeApiServer(grpcServer, &project_code_api_serv.ProjectCodeApiImpl{})
	project_idea_api.RegisterProjectIdeaApiServer(grpcServer, &project_idea_api_serv.ProjectIdeaApiImpl{})
	project_alarm_api.RegisterProjectAlarmApiServer(grpcServer, &project_alarm_api_serv.ProjectAlarmApiImpl{})
	project_bulletin_api.RegisterProjectBulletinApiServer(grpcServer, &project_bulletin_api_serv.ProjectBulletinApiImpl{})
	api_collection_api.RegisterApiCollectionApiServer(grpcServer, &api_collection_api_serv.ApiCollectionApiImpl{})
	http_custom_api.RegisterHttpCustomApiServer(grpcServer, &http_custom_api_serv.HttpCustomApiImpl{})
	project_watch_api.RegisterProjectWatchApiServer(grpcServer, &project_watch_api_serv.ProjectWatchApiImpl{})
	project_comment_api.RegisterProjectCommentApiServer(grpcServer, &project_comment_api_serv.ProjectCommentApiImpl{})
	project_testcase_api.RegisterProjectTestCaseApiServer(grpcServer, &project_testcase_api_serv.ProjectTestCaseApiImpl{})
	project_recycle_api.RegisterProjectRecycleApiServer(grpcServer, &project_recycle_api_serv.ProjectRecycleApiImpl{})
	project_git_api.RegisterProjectGitApiServer(grpcServer, &project_git_api_serv.ProjectGitApiImpl{})
	project_server_api.RegisterProjectServerApiServer(grpcServer, &project_server_api_serv.ProjectServerApiImpl{})
	idea_store_api.RegisterIdeaStoreApiServer(grpcServer, &idea_store_api_serv.IdeaStoreApiImpl{})
	org_api.RegisterOrgApiServer(grpcServer, org_api_serv.NewOrgApiImpl(servCfg.DataBase.FileStore.RemoteAddr))
	org_member_api.RegisterOrgMemberApiServer(grpcServer, &org_member_api_serv.OrgMemberApiImpl{})
	org_okr_api.RegisterOrgOkrApiServer(grpcServer, &org_okr_api_serv.OrgOkrApiImpl{})
	org_report_api.RegisterOrgReportApiServer(grpcServer, &org_report_api_serv.OrgReportApiImpl{})
	org_forum_api.RegisterOrgForumApiServer(grpcServer, org_forum_api_serv.NewOrgForumApiImpl(servCfg.DataBase.FileStore.RemoteAddr))
	org_evaluate_api.RegisterOrgEvaluateApiServer(grpcServer, &org_evaluate_api_serv.OrgEvaluateApiImpl{})
	widget_store_api.RegisterWidgetStoreApiServer(grpcServer, &widget_store_api_serv.WidgetStoreApiImpl{})
	sw_store_api.RegisterSwStoreApiServer(grpcServer, &sw_store_api_serv.SwStoreApiImpl{})
	feedback_api.RegisterFeedBackApiServer(grpcServer, &feedback_api_serv.FeedBackApiImpl{})
	project_dataview_api.RegisterProjectDataViewApiServer(grpcServer, &project_dataview_api_serv.ProjectDataViewApiImpl{})
	project_review_api.RegisterProjectReviewApiServer(grpcServer, &project_review_api_serv.ProjectReviewApiImpl{})
	dataview_chat_api.RegisterDataViewChatApiServer(grpcServer, &dataview_chat_api_serv.DataViewChatApiImpl{})
	roadmap_api.RegisterRoadmapApiServer(grpcServer, &roadmap_api_serv.RoadmapApiImpl{})
	roadmap_content_api.RegisterRoadmapContentApiServer(grpcServer, roadmap_content_api_serv.NewRoadmapContentApiImpl(&servCfg.Admin))
	roadmap_state_api.RegisterRoadmapStateApiServer(grpcServer, &roadmap_state_api_serv.RoadmapStateApiImpl{})
	roadmap_user_api.RegisterRoadmapUserApiServer(grpcServer, &roadmap_user_api_serv.RoadmapUserApiImpl{})
	project_triger_api.RegisterProjectTrigerApiServer(grpcServer, &project_triger_api_serv.ProjectTrigerApiImpl{})

	if servCfg.Admin.Enable {
		admin_auth_api.RegisterAdminAuthApiServer(grpcServer, admin_auth_api_serv.NewAdminAuthApiImpl(&servCfg.Admin, servCfg.GlobalServer))
		admin_auth_api.RegisterAdminAuthAdminApiServer(grpcServer, admin_auth_user_api_serv.NewAdminAuthAdminApiImpl(&servCfg.Admin))
		project_api.RegisterProjectAdminApiServer(grpcServer, admin_project_api_serv.NewProjectAdminApiImpl(&servCfg.Admin))
		project_member_api.RegisterProjectMemberAdminApiServer(grpcServer, admin_project_member_api_serv.NewProjectMemberAdminApiImpl(&servCfg.Admin))
		user_api.RegisterUserAdminApiServer(grpcServer, admin_user_api_serv.NewUserAdminApiImpl(&servCfg.Admin))
		user_resume_api.RegisterUserResumeAdminApiServer(grpcServer, admin_user_resume_api_serv.NewUserResumeAdminApiImpl(&servCfg.Admin))
		client_cfg_api.RegisterClientCfgAdminApiServer(grpcServer, admin_client_cfg_api_serv.NewClientCfgAdminApiImpl(&servCfg.Admin))
		events_api.RegisterEventsAdminApiServer(grpcServer, admin_events_api_serv.NewEventsAdminApiImpl(&servCfg.Admin))
		appstore_api.RegisterAppstoreAdminApiServer(grpcServer, admin_appstore_api_serv.NewAppstoreAdminImpl(&servCfg.Admin))
		idea_store_api.RegisterIdeaStoreAdminApiServer(grpcServer, admin_idea_api_serv.NewIdeaStoreAdminApiImpl(&servCfg.Admin))
		widget_store_api.RegisterWidgetStoreAdminApiServer(grpcServer, admin_widget_store_api_serv.NewWidgetStoreAdminApiImpl(&servCfg.Admin))
		sw_store_api.RegisterSwStoreAdminApiServer(grpcServer, admin_sw_strore_api_serv.NewSwStoreAdminApiImpl(&servCfg.Admin))
		org_api.RegisterOrgAdminApiServer(grpcServer, admin_org_api_serv.NewOrgAdminApiImpl(&servCfg.Admin))
		org_member_api.RegisterOrgMemberAdminApiServer(grpcServer, admin_org_member_api_serv.NewOrgMemberAdminApiImpl(&servCfg.Admin))
		keyword_api.RegisterKeywordAdminApiServer(grpcServer, admin_keyword_api_serv.NewKeywordAdminApiImpl(&servCfg.Admin))
		feedback_api.RegisterFeedBackAdminApiServer(grpcServer, admin_feedback_api_serv.NewFeedBackAdminApiImpl(&servCfg.Admin))
		roadmap_api.RegisterRoadmapAdminApiServer(grpcServer, admin_roadmap_api_serv.NewRoadmapAdminApiImpl(&servCfg.Admin))
	}

	addr, err := net.ResolveTCPAddr("tcp4", fmt.Sprintf("0.0.0.0:%d", servCfg.GrpcPort))
	if err != nil {
		exitChan <- err
		return
	}
	li, err := net.ListenTCP("tcp4", addr)
	if err != nil {
		exitChan <- err
		return
	}
	fmt.Println("server start......")
	err = grpcServer.Serve(li)
	if err != nil {
		exitChan <- err
		return
	}
}

func initLogger(logpath string, lv zapcore.Level) *zap.Logger {
	hook := lumberjack.Logger{
		Filename:   logpath,
		LocalTime:  true,
		MaxSize:    100,
		MaxBackups: 30,
		MaxAge:     30,
		Compress:   false,
	}

	encoderConfig := zapcore.EncoderConfig{
		TimeKey:        "time",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "linenum",
		MessageKey:     "msg",
		StacktraceKey:  "stacktrace",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.CapitalLevelEncoder,
		EncodeTime:     zapcore.ISO8601TimeEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.FullCallerEncoder,
		EncodeName:     zapcore.FullNameEncoder,
	}

	core := zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderConfig),
		zapcore.AddSync(&hook),
		lv,
	)
	return zap.New(core)
}

func main() {
	if len(os.Args) != 2 {
		fmt.Printf("Usage:%s [config file]\n", os.Args[0])
		return
	}
	servCfg, err := config.ReadConfig(os.Args[1])
	if err != nil {
		fmt.Println(err)
		return
	}

	if servCfg.Trace.Addr != "" {
		//init trace
		shutDownFn, err := setupOtel(&servCfg.Trace, "linksaasApi", VERSION)
		if err != nil {
			fmt.Println(err)
			return
		}

		defer shutDownFn(context.Background())
	}

	//init logger
	grpcLogger := initLogger(servCfg.Logging.Grpc, zap.WarnLevel)
	defer grpcLogger.Sync()
	taskLogger := initLogger(servCfg.Logging.Task, zap.InfoLevel)
	defer taskLogger.Sync()
	webhookLogger := initLogger(servCfg.Logging.Webhook, zap.InfoLevel)
	defer taskLogger.Sync()
	errLogger := initLogger(servCfg.Logging.Error, zap.InfoLevel)
	defer errLogger.Sync()
	go func() {
		for {
			time.Sleep(30 * time.Second)
			grpcLogger.Sync()
			taskLogger.Sync()
			taskLogger.Sync()
			errLogger.Sync()
		}
	}()

	mongoDb, err := connMongoDb(servCfg.DataBase.Mongo.Url, servCfg.DataBase.Mongo.DataBase)
	if err != nil {
		fmt.Println(err)
		return
	}
	rdb := redis.NewClient(&redis.Options{
		Addr:     servCfg.DataBase.Redis.Addr,
		Password: servCfg.DataBase.Redis.PassWord,
	})

	err = dao.InitDao(mongoDb, rdb)
	if err != nil {
		fmt.Println(err)
		return
	}

	err = upgrade.UpgradeDb()
	if err != nil {
		fmt.Println(err)
		return
	}

	err = notice_serv.Init(rdb)
	if err != nil {
		fmt.Println(err)
		return
	}

	exitChan := make(chan error, 10)
	go func() {
		sigChan := make(chan os.Signal, 1)
		signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
		<-sigChan
		exitChan <- errors.New("catch signal")
	}()
	bg_runner.StartBgRunner(4, taskLogger)
	go metric_serv.RunServer(servCfg.MetricPort, exitChan)
	if servCfg.ClientCfg.MaxMailAccountPerUser > 0 && servCfg.ClientCfg.MaxMailCountPerUser > 0 && servCfg.ClientCfg.UserMailDomain != "" {
		go mail_serv.RunServer(&servCfg.ClientCfg, exitChan)
	}
	go runGrpcServer(servCfg, grpcLogger, errLogger, exitChan)
	go runWebServer(servCfg.HttpPort, webhookLogger, exitChan)
	err = <-exitChan
	fmt.Println(err)
	if grpcServer != nil {
		fmt.Println("graceful stop server")
		grpcServer.GracefulStop()
		fmt.Println("wait exiting.....")
		time.Sleep(3 * time.Second)
	}
}
